//
//  UIButton+Extension.swift
//  TuneMate
//
//  Created by 丸子 on 2023/11/23.
//

import UIKit
enum ButtomMode {
    case Top
    case Bottom
    case Left
    case Right
}
enum MKButtonEdgeInsetsStyle: Int {
    case Top    // image在上，label在下
    case Left  // image在左，label在右
    case Bottom // image在下，label在上
    case Right // image在右，label在左
}
fileprivate var touchKey: Void?
fileprivate var topKey: Void?
fileprivate var bottomKey: Void?
fileprivate var leftKey: Void?
fileprivate var rightKey: Void?
extension UIButton {
    
    func setImage(_ image: UIImage?, tintColor: UIColor, for state: UIControl.State) {
        self.setImage(image?.withRenderingMode(.alwaysTemplate), for: state)
        self.imageView?.tintColor = tintColor
    }

    func layoutButtonWithEdgeInsetsStyle(_ style:MKButtonEdgeInsetsStyle, space:CGFloat!)
    {
        let imageWith = self.imageView?.frame.size.width ?? 0.0
        let imageHeight = self.imageView?.frame.size.height ?? 0.0
        
        let labelWidth = self.titleLabel?.intrinsicContentSize.width ?? 0.0
        let labelHeight = self.titleLabel?.intrinsicContentSize.height ?? 0.0
        
        var imageEdgeInsets:UIEdgeInsets = UIEdgeInsets.zero
        var labelEdgeInsets:UIEdgeInsets = UIEdgeInsets.zero
        
        switch (style)
        {
        case .Top:
            imageEdgeInsets = UIEdgeInsets(top: -labelHeight - space / 2.0, left: 0, bottom: 0, right: -labelWidth)
            labelEdgeInsets = UIEdgeInsets(top: 0, left: -imageWith, bottom: -imageHeight-space/2.0, right: 0)
            break
        case .Left:
            imageEdgeInsets = UIEdgeInsets(top: 0, left: -space/2.0, bottom: 0, right: space/2.0)
            labelEdgeInsets = UIEdgeInsets(top: 0, left: space/2.0, bottom: 0, right: -space/2.0)
            break
        
        case .Bottom:
            imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: -labelHeight-space/2.0, right: -labelWidth)
            labelEdgeInsets = UIEdgeInsets(top: -imageHeight-space/2.0, left: -imageWith, bottom: 0, right: 0)
            break
        
        case .Right:
            imageEdgeInsets = UIEdgeInsets(top: 0, left: labelWidth+space/2.0, bottom: 0, right: -labelWidth-space/2.0)
            labelEdgeInsets = UIEdgeInsets(top: 0, left: -imageWith-space/2.0, bottom: 0, right: imageWith+space/2.0)
            break
        }
        
        self.titleEdgeInsets = labelEdgeInsets
        self.imageEdgeInsets = imageEdgeInsets
    }
    
    /// 快速调整图片与文字位置
    ///
    /// - Parameters:
    ///   - buttonMode: 图片所在位置
    ///   - spacing: 文字和图片之间的间距
    func locationAdjust(buttonModel: ButtomMode,spacing: CGFloat) {
        let imageSize = self.imageRect(forContentRect: self.frame)
        let titleFont = self.titleLabel?.font!
        let titleSize = titleLabel?.text?.size(withAttributes: [kCTFontAttributeName as NSAttributedString.Key: titleFont!]) ?? CGSize.zero
        var titleInsets: UIEdgeInsets
        var imageInsets: UIEdgeInsets
        switch (buttonModel){
        case .Top:
            titleInsets = UIEdgeInsets(top: (imageSize.height + titleSize.height + spacing)/2,
                                       left: -(imageSize.width), bottom: 0, right: 0)
            imageInsets = UIEdgeInsets(top: -(imageSize.height + titleSize.height + spacing)/2, left: 0, bottom: 0, right: -titleSize.width)
        case .Bottom:
            titleInsets = UIEdgeInsets(top: -(imageSize.height + titleSize.height + spacing)/2,
                                       left: -(imageSize.width), bottom: 0, right: 0)
            imageInsets = UIEdgeInsets(top: (imageSize.height + titleSize.height + spacing)/2, left: 0, bottom: 0, right: -titleSize.width)
        case .Left:
            titleInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: -spacing)
            imageInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        case .Right:
            titleInsets = UIEdgeInsets(top: 0, left: -(titleSize.width + spacing), bottom: 0, right: 0)
            imageInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0,
                                       right: -(titleSize.width * 2 + spacing))
        }
        self.titleEdgeInsets = titleInsets
        self.imageEdgeInsets = imageInsets
    }
    
    private func image(withColor color: UIColor) -> UIImage? {
        let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
        UIGraphicsBeginImageContext(rect.size)
        let context = UIGraphicsGetCurrentContext()
        
        context?.setFillColor(color.cgColor)
        context?.fill(rect)
        
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return image
    }
    
    public func setBackgroundColor(_ color: UIColor, for state: UIControl.State) {
        self.setBackgroundImage(image(withColor: color), for: state)
    }
    
    static func button(_ title: String? = nil, titleColor: UIColor? = nil, titleFont: UIFont? = nil, image: UIImage? = nil, backImage: UIImage? = nil, backColor: UIColor? = nil) -> UIButton {
        let button: UIButton = UIButton(type: .custom)
        if let tit = title {
            button.setTitle(tit, for: .normal)
        }
        
        if let titColor = titleColor {
            button.setTitleColor(titColor, for: .normal)
        }
        
        if let titFont = titleFont {
            button.titleLabel?.font = titFont
        }
        
        if let img = image {
            button.setImage(img, for: .normal)
            button.setImage(img, for: .highlighted)
        }
        
        if let bImg = backImage {
            button.setBackgroundImage(bImg, for: .normal)
        }
        
        if let bColor = backColor {
            button.backgroundColor = bColor
        }
        
        return button
    }
    
    private struct AssociatedKeys {
            static var touchAreaSize: CGSize = .zero
        }

        var touchAreaSize: CGSize {
            get {
                if let value = objc_getAssociatedObject(self, &AssociatedKeys.touchAreaSize) as? NSValue {
                    return value.cgSizeValue
                } else {
                    return .zero
                }
            }
            set(newValue) {
                objc_setAssociatedObject(self, &AssociatedKeys.touchAreaSize, NSValue(cgSize: newValue), objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        }

        open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
            if self.touchAreaSize == .zero || !self.isEnabled || self.isHidden {
                return super.point(inside: point, with: event)
            }

            let relativeFrame = self.bounds
            let newBounds = CGRect(x: relativeFrame.origin.x - touchAreaSize.width / 2,
                                   y: relativeFrame.origin.y - touchAreaSize.height / 2,
                                   width: relativeFrame.size.width + touchAreaSize.width,
                                   height: relativeFrame.size.height + touchAreaSize.height)
            return newBounds.contains(point)
        }
    
    /**< 点击闭包 */
    func setClosureTouchUpInside_k(closure: @escaping () -> Void) {
        self.addTarget(self, action: #selector(callActionClosure(sender:)), for: .touchUpInside)
        objc_setAssociatedObject(self, &touchKey, closure, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }
    
    @objc fileprivate func callActionClosure(sender: UIButton) {
        let closure = objc_getAssociatedObject(self, &touchKey) as? () -> Void
        closure?()
    }
    
    /**< 扩大点击范围 */
    func setEnlargeEdgeTop_k(top: CGFloat, bottom: CGFloat, left: CGFloat, right: CGFloat) {
        objc_setAssociatedObject(self, &topKey, top, .OBJC_ASSOCIATION_COPY_NONATOMIC);
        objc_setAssociatedObject(self, &bottomKey, bottom, .OBJC_ASSOCIATION_COPY_NONATOMIC);
        objc_setAssociatedObject(self, &leftKey, left, .OBJC_ASSOCIATION_COPY_NONATOMIC);
        objc_setAssociatedObject(self, &rightKey, right, .OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    
    var normalImage: UIImage? {
        set { setImage(newValue, for: .normal) }
        get { return image(for: .normal) }
    }
    
    var normalBackgroundImage: UIImage? {
        set { setBackgroundImage(newValue, for: .normal) }
        get { return backgroundImage(for: .normal) }
    }
    
    var normalTitle: String? {
        get { return title(for: .normal) }
        set { setTitle(newValue, for: .normal) }
    }
    
    var normalTitleColor: UIColor? {
        get { return titleColor(for: .normal) }
        set { setTitleColor(newValue, for: .normal) }
    }
    

    ///selected
    var selectedImage: UIImage? {
        set { setImage(newValue, for: .selected) }
        get { return image(for: .selected) }
    }
    
    var selectedBackgroundImage: UIImage? {
        set { setBackgroundImage(newValue, for: .selected) }
        get { return backgroundImage(for: .selected) }
    }
    
    var selectedTitle: String? {
        get { return title(for: .selected) }
        set { setTitle(newValue, for: .selected) }
    }
    
    var selectedTitleColor: UIColor? {
        get { return titleColor(for: .selected) }
        set { setTitleColor(newValue, for: .selected) }
    }
    
    var titleFont: UIFont? {
        get { return titleLabel?.font }
        set { titleLabel?.font = newValue }
    }
}

class XFButton: UIButton {
    override var isHighlighted: Bool {
        didSet {
            super.isHighlighted = false
        }
    }
}
